JS 30 是由加拿大的全端工程師 Wes Bos 免費提供的 JavaScript 簡單應用課程,課程主打 No Frameworks、No Compilers、No Libraries、No Boilerplate 在30天的30部教學影片裡,建立30個JavaScript的有趣小東西。
另外,Wes Bos 也很無私地在 Github 上公開了所有 JS 30 課程的程式碼,有興趣的話可以去 fork 或下載。
今天也是複習回,主要是拿來重新複習下 Array 的map()和reduce()的用法。我們的最終目標是算出影片的長度總和並以時、分、秒呈現在 console裡。
以下是我們要用來計算影片總時數的清單,其中data-time屬性值標示出影片的長度。
<ul class="videos">
<li data-time="5:43">
Video 1
</li>
<li data-time="2:33">
Video 2
</li>
<li data-time="3:45">
Video 3
</li>
<li data-time="0:47">
Video 4
</li>
<li data-time="5:21">
Video 5
</li>
<!--以下省略-->
<ul>

一開始,我們宣告常數timeNodes用來放我們取得的所有清單項目(<li>~</li>),因為之後會用到 Array 的reduce()、map(),這裡就順便把NodeList用Array.from()轉換成 Array。
const timeNodes = Array.from(document.querySelectorAll('[data-time]'));
宣告常數seconds存入所有影片的秒數總和。
第一個map()幫我們取得個別影片時間所構成的陣列(分:秒)。
第二個map()幫我們把影片時間的分和秒切開(間隔符號:),第三個map()幫我們把陣列中的元素都轉換成浮點數,最後把影片的長度都換成秒(mins * 60 + secs)。
把影片長度都換成以秒為單位後,就可以用reduce()將它們加在一起囉!
const seconds = timeNodes
.map(node => node.dataset.time)
.map(timeCode => {
const [mins, secs] = timeCode.split(':').map(parseFloat);
return (mins * 60) + secs;
})
.reduce((total, vidSeconds) => total + vidSeconds);
第一次map()後產生的陣列
第二、三次map()後產生的陣列
所有影片長度的秒數總和
接下來,把得到的總秒數換成時、分、秒的形式就完成本日的目標囉!
let secondsLeft = seconds;
//Math.floor() 回傳小於等於所給數字的最大整數
const hours = Math.floor(secondsLeft / 3600);
secondsLeft = secondsLeft % 3600;
const mins = Math.floor(secondsLeft / 60);
secondsLeft = secondsLeft % 60;
console.log(hours, mins, secondsLeft);

Array.from()
parseFloat()
Array.prototype.map()
Array.prototype.reduce()
Math.floor()